using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;

using LogAnalyzerIIS.LogClasses;
using LogAnalyzerIIS.Helpers;
using LogAnalyzerIIS.Objects;
using LogAnalyzerIIS.WizardForms;

namespace LogAnalyzerIIS.DemoWizard
{
	public partial class MainWizard : Form
	{
		// session object to process
		public Session session;

		// thread object used for downloading/processing log files and report creating
		Thread thread = null;

		private StartPage wizardStartPage = StartPage.Servers;

		/// <summary>
		/// enumeration of possible start pages of Wizard
		/// </summary>
		public enum StartPage
		{
			Servers,
			Applications,
		}


		public MainWizard(StartPage startPage, Session currentSession)
		{
			InitializeComponent();

			session = currentSession;

			txtReportName.Text = session.Name;

			wizardStartPage = startPage;

			if (wizardControl.SelectedIndex == 0)
				btnBack.Enabled = false;
		}

		private void btnNext_Click(object sender, EventArgs e)
		{
			wizardControl.SelectedIndex++;


			if (wizardControl.SelectedIndex == wizardControl.TabPages.Count - 1)
				btnNext.Enabled = false;
		}

		private void btnCancel_Click(object sender, EventArgs e)
		{
			if (thread != null)
			{
				thread.Abort();
				thread.Join();
				thread = null;
			}
			this.Close();
		}

		private void btnBack_Click(object sender, EventArgs e)
		{
			wizardControl.SelectedIndex--;

			if (wizardControl.SelectedIndex == 0)
				btnBack.Enabled = false;
		}

		private void wizardControl_Selecting(object sender, TabControlCancelEventArgs e)
		{
			if (wizardControl.SelectedIndex < (int)wizardControl.Tag)
			{
				if (wizardControl.SelectedIndex + (int)wizardControl.Tag == 5)
				{
					btnBack.Enabled = false;
					wizardControl.SelectedTab = pageChooseServers;
				}
				return;
			}
		}

		private void wizardControl_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (wizardControl.SelectedIndex > (int)wizardControl.Tag)
			{
				switch (wizardControl.SelectedIndex)
				{
					case 0:
						btnNext.Enabled = false;
						break;
					case 1:
						// Next pressed on the Servers page
						SaveServers();
						GetServerFileInformation();
						session.Save();
						break;

					case 2:
						// Next pressed on the Downloading file page
						LoadWebApplicationList();
						break;

					case 3:
						// Next pressed on the Applications page
						// initialize the progress page
						reportProgressBar.Value = 0;
						reportProgressBar.Maximum = GetReportInputsCount();
						reportProgressBar.Step = 1;

						btnNext.Enabled = false;
						btnBack.Enabled = false;

						foreach (WebApplication webApplication in lbApplications.Items)
						{
							webApplication.StartDate = dtpReportPeriodFrom.Value;
							webApplication.EndDate = dtpReportPeriodTo.Value;
						}

						lbReportProgress.Items.Clear();
						lbReportProgress.Items.Add(ThreadingHelper.FormatLogRow("Start"));

						thread = new Thread(new ThreadStart(CreateReports));
						thread.Start();
						break;

					//case 7:
					//    // Next pressed on the Creating reports page
					//    wizardControl.NextEnabled = false;
					//    session.Save();
					//    this.Close();
					//    break;
				}
			}
			wizardControl.Tag = wizardControl.SelectedIndex;
		}

		private void DemoWizardForm_Load(object sender, EventArgs e)
		{
			LoadServerPageControls();

			wizardControl.Tag = (int)0;

			switch (wizardStartPage)
			{
				// start wizard from the servers page 
				case StartPage.Servers:
					wizardControl.SelectedTab = pageChooseServers;
					break;

				// start wizard from the applications page
				case StartPage.Applications:
					LoadWebApplicationList();
					wizardControl.SelectedTab = pageReportOptions;
					break;
			}
		}

		#region server page methods
		/// <summary>
		/// Loads Servers page with values
		/// </summary>
		private void LoadServerPageControls()
		{
			chkClearLocalLogs.Checked = session.ClearDownloadedLogFiles;
			chkClearServerLogs.Checked = session.ClearServerLogFiles;

			lbServers.Items.Clear();

			// add servers to the list with appropriate checkboxes values
			foreach (ServerRecord server in session.ServerRecords)
				lbServers.Items.Add(server, server.Enabled);

			if (lbServers.Items.Count > 0)
				lbServers.SelectedIndex = 0;

			lbServers_SelectedIndexChanged(lbServers, null);

			// try to enable Next button of the wizard
			if (wizardControl.SelectedTab == pageChooseServers)
				btnNext.Enabled = EnableServersNext(0);
		}

		/// <summary>
		/// Saves values from the Servers page to the session object
		/// </summary>
		private void SaveServers()
		{
			session.ServerRecords.Clear();

			foreach (ServerRecord server in lbServers.Items)
				session.ServerRecords.Add(server);

			session.ClearDownloadedLogFiles = chkClearLocalLogs.Checked;
			session.ClearServerLogFiles = chkClearServerLogs.Checked;
		}

		/// <summary>
		/// Checks whether Next button on Servers wizard page can be enabled
		/// </summary>
		/// <param name="shift">Number that should be added to checked items count to get it actual value</param>
		/// <returns>True if Next button can be enabled, false otherwise</returns>
		private bool EnableServersNext(int shift)
		{
			// Next button can be enabled if:
			// 1. Number of servers to process is 1 or more
			// 2. Server path isn't empty and doesn't contain invalid path characters
			// 3. Server alias isn't empty and doesn't contain invalid filename characters
			if (txtServerPath.Text != "" && lbServers.CheckedIndices.Count + shift > 0 &&
					(txtServerPath.Text.IndexOfAny(Path.GetInvalidPathChars()) < 0) &&
					txtServerAlias.Text != "" &&
					(txtServerAlias.Text.IndexOfAny(Path.GetInvalidFileNameChars()) < 0))
				return true;
			else
				return false;
		}


		private void btnAddNewServer_Click(object sender, EventArgs e)
		{
			// adding servers to the server list
			ServerListForm serverListForm = new ServerListForm(lbServers.Items);

			if (serverListForm.ShowDialog() == DialogResult.OK)
			{
				int lastAddIndex = -1;

				for (int i = 0; i < serverListForm.ServerNames.Count; i++)
				{
					// see if the server already exists in the list
					bool serverExists = false;
					for (int j = 0; j < lbServers.Items.Count; j++)
					{
						if (lbServers.Items[j] == serverListForm.ServerNames[i])
						{
							serverExists = true;
							break;
						}
					}

					// add the server to the wizard listbox
					if (!serverExists)
					{
						ServerRecord server = serverListForm.ServerNames[i];
						server.Enabled = true;

						lastAddIndex = lbServers.Items.Add(server, true);
					}
				}

				// select the last added server
				if (lastAddIndex > -1)
				{
					lbServers.SelectedIndex = lastAddIndex;
					lbServers_SelectedIndexChanged(lbServers, null);
				}
			}
		}

		private void lbServers_SelectedIndexChanged(object sender, EventArgs e)
		{
			// if item has been selected, enable corresponding controls, otherwise disable them
			if (lbServers.SelectedIndex >= 0)
			{
				ServerRecord server = lbServers.SelectedItem as ServerRecord;

				txtServerPath.Text = server.Path;
				txtServerAlias.Text = server.Alias = server.Name;
				txtServerPath.Enabled = true;
				txtServerAlias.Enabled = true;
				btnBrowseServer.Enabled = true;
			}
			else
			{
				txtServerPath.Text = "";
				txtServerAlias.Text = "";
				txtServerPath.Enabled = false;
				txtServerAlias.Enabled = false;
				btnBrowseServer.Enabled = false;
			}
		}

		private void btnBrowseServer_Click(object sender, EventArgs e)
		{
			try
			{
				folderBrowserDialog.SelectedPath = txtServerPath.Text;
			}
			finally
			{
				if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
				{
					txtServerPath.Text = folderBrowserDialog.SelectedPath;
					txtServerPath_Validated(txtServerPath, null);
				}
			}
		}

		private void txtServerPath_Validated(object sender, EventArgs e)
		{
			if (lbServers.SelectedIndex < 0)
				return;

			if (lbServers.SelectedItem != null)
				(lbServers.SelectedItem as ServerRecord).Path = txtServerPath.Text;
		}

		private void txtServerAlias_Validated(object sender, EventArgs e)
		{
			if (lbServers.SelectedIndex < 0)
				return;

			if (lbServers.SelectedItem != null)
			{
				(lbServers.SelectedItem as ServerRecord).Alias = txtServerAlias.Text;
				(lbServers.SelectedItem as ServerRecord).Name = txtServerAlias.Text;
			}
		}

		private void lbServers_ItemCheck(object sender, ItemCheckEventArgs e)
		{
			int shift;
			if (e.NewValue == CheckState.Checked)
				shift = 1;
			else
				shift = -1;

			btnNext.Enabled = EnableServersNext(shift);
		}

		private void btnRemoveServer_Click(object sender, EventArgs e)
		{
			if (lbServers.SelectedIndex < 0)
				return;

			lbServers.Items.RemoveAt(lbServers.SelectedIndex);

			if (lbServers.SelectedIndex >= 0)
				lbServers.SelectedIndex = 0;

			lbServers_SelectedIndexChanged(lbServers, null);
		}

		private void tbServerPath_TextChanged(object sender, EventArgs e)
		{
			btnNext.Enabled = EnableServersNext(0);
		}

		#endregion

		#region ApplicationPage methods

		private void tbReportName_TextChanged(object sender, EventArgs e)
		{
			EnableApplicationsPageNextButton(0);
		}

		/// <summary>
		/// Checks whether Next button on Applications wizard page can be enabled
		/// </summary>
		/// <param name="shift">Number to add to checked items count to get the actual count (for checked events)</param>
		private void EnableApplicationsPageNextButton(int shift)
		{
			// Next button can be enabled if:
			// 1. Number of applications is 1 or more
			// 2. Output name isn't empty and doesn't contain invalid filename characters
			if (txtReportName.Text != "" &&
					lbApplications.CheckedIndices.Count + shift > 0 &&
					(txtReportName.Text.IndexOfAny(Path.GetInvalidFileNameChars()) < 0))
				btnNext.Enabled = true;
			else
				btnNext.Enabled = false;
		}

		/// <summary>
		/// Fill Web Applications page with values
		/// </summary>
		private void LoadWebApplicationList()
		{
			// set fake date as initial values for max/min date detecting
			DateTime minStart = DateTime.MaxValue;
			DateTime maxEnd = DateTime.MinValue;

			lbApplications.Items.Clear();

			for (int serverIndex = 0; serverIndex < session.ServerRecords.Count; serverIndex++)
			{
				if (session.ServerRecords[serverIndex].Enabled)
				{
					foreach (WebApplication webApplication in session.ServerRecords[serverIndex].WebApplications)
					{
						lbApplications.Items.Add(webApplication, webApplication.Enabled);

						if (minStart > webApplication.StartDate)
							minStart = webApplication.StartDate;

						if (maxEnd < webApplication.EndDate)
							maxEnd = webApplication.EndDate;
					}
				}
			}

			// if start date is set, set the start date picker
			if (minStart != DateTime.MaxValue)
				dtpReportPeriodFrom.Value = minStart;

			// if end date is set, set the start date picker
			if (maxEnd != DateTime.MinValue)
				dtpReportPeriodTo.Value = maxEnd;

			// select the first item of the list if it exists
			if (lbApplications.Items.Count > 0)
				lbApplications.SelectedIndex = 0;

			// try applications page button
			if (wizardControl.SelectedTab == pageReportOptions)
				EnableApplicationsPageNextButton(0);
		}

		private void lbApplications_ItemCheck(object sender, ItemCheckEventArgs e)
		{
			WebApplication application = (WebApplication)lbApplications.Items[e.Index];

			if (e.NewValue == CheckState.Checked)
			{
				application.Enabled = true;
				EnableApplicationsPageNextButton(1);
			}
			else
			{
				application.Enabled = false;
				EnableApplicationsPageNextButton(-1);
			}
		}

		private void lbApplications_SelectedIndexChanged(object sender, EventArgs e)
		{
			// if item has been selected, enable corresponding controls
			if (lbApplications.SelectedIndex > -1)
			{
				dtpReportPeriodFrom.Enabled = true;
				dtpReportPeriodTo.Enabled = true;
			}
			else
			{
				dtpReportPeriodFrom.Enabled = false;
				dtpReportPeriodTo.Enabled = false;
			}
		}

		#endregion

		#region report processing

		/// <summary>
		/// Create reports based on the current session (thread procedure)
		/// </summary>
		private void CreateReports()
		{
			Delegate delegatePerformStep = new ThreadingHelper.ProgressBarDelegate(PerformProgressStep);
			Delegate delegateSetString = new ThreadingHelper.LabelDelegate(SetString);
			Delegate delegateAddItemToListBox = new ThreadingHelper.ListBoxDelegate(AddItemToListBox);

			Excel.Workbook workbook = Globals.ThisAddIn.Application.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
			Excel.Worksheet worksheet = workbook.Worksheets[1] as Excel.Worksheet;

			bool firstWorksheet = true;
			foreach (ServerRecord server in session.ServerRecords)
			{
				if (server.Enabled)
				{
					foreach (WebApplication application in server.WebApplications)
					{
						if (application.Enabled)
						{
							// update progress list box
							Invoke(delegateAddItemToListBox, new Object[] { lbReportProgress, ThreadingHelper.FormatLogRow("Creating report for " + application.Name) });

							StatisticsReader statisticsReader = new StatisticsReader(application.StartDate, application.EndDate);
							foreach (FilePath applicationFilePath in application.LogFiles)
							{
								// update progress list box
								Invoke(delegateAddItemToListBox, new Object[] { lbReportProgress, ThreadingHelper.FormatLogRow("Loading statistics from log file " + applicationFilePath.ToString()) });
								// add log file to the statistics pool
								string loadingResult = statisticsReader.LoadStatisticsFromLogFile(applicationFilePath.FullPath);
								// update progress list box
								Invoke(delegateAddItemToListBox, new Object[] { lbReportProgress, ThreadingHelper.FormatLogRow(loadingResult) });
								// update progress bar
								Invoke(delegatePerformStep, new Object[] { reportProgressBar });
							}

							// if this is the first iteration, don't create new worksheet
							if (firstWorksheet)
							{
								worksheet = workbook.Worksheets[1] as Excel.Worksheet;
								firstWorksheet = false;
							}
							else
								worksheet = workbook.Worksheets.Add(Type.Missing, worksheet, Type.Missing, Type.Missing) as Excel.Worksheet;

							// update progress list box
							Invoke(delegateAddItemToListBox, new Object[] { lbReportProgress, ThreadingHelper.FormatLogRow("Creating output for " + application.Name) });

							// give to the worksheet application's name (Excel supports a max of 31 chars)
							string worksheetName = application.Name;
							if (worksheetName.Length > 31)
								worksheetName = application.Name.Substring(0, 31);

							worksheet.Name = worksheetName;

							// output  statistics to the worksheet
							StatisticsWriter statisticsWriter = new StatisticsWriter(statisticsReader.statisticsPool);
							string outputResult = statisticsWriter.PrintAllToWS(worksheet);
							// update progress list box
							Invoke(delegateAddItemToListBox, new Object[] { lbReportProgress, ThreadingHelper.FormatLogRow(outputResult) });
							// update progress bar
							Invoke(delegatePerformStep, new Object[] { reportProgressBar });
						}
					}
				}
			}
			try
			{
				// save report file with session name to the output folder
				// (delete if it already exists)
				string outpath = session.OutputFolder + "\\" + txtReportName.Text + ".xlsx";
				try
				{
					if (File.Exists(outpath))
						File.Delete(outpath);

					workbook.SaveAs(outpath, Type.Missing, Type.Missing, Type.Missing, false,
									Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing,
									Type.Missing, Type.Missing, Type.Missing, Type.Missing);
				}
				catch (Exception ex)
				{
					// update progress list box
					Invoke(delegateAddItemToListBox, new Object[] { lbReportProgress, ThreadingHelper.FormatLogRow("Error: " + ex.Message) });
				}

				// add ouput files to the session output files list
				bool outputFileFound = false;
				foreach (FilePath filePath in session.ReportFilepaths)
				{
					if (filePath.FullPath == outpath)
					{
						outputFileFound = true;
						break;
					}
				}

				if (!outputFileFound)
					session.ReportFilepaths.Add(new FilePath(outpath));
			}
			finally
			{
				Delegate delegateFinalizeThread = new ThreadingHelper.VoidDelegate(FinalizeThread);
				BeginInvoke(delegateFinalizeThread);
			}
		}


		/// <summary>
		/// Get number of log files in order to indicate current progress during report creating
		/// </summary>
		private int GetReportInputsCount()
		{
			int res = 0;
			foreach (ServerRecord server in session.ServerRecords)
			{
				foreach (WebApplication application in server.WebApplications)
				{
					if (application.Enabled)
						res += application.LogFiles.Count + 1;
				}
			}

			return res;
		}

		#endregion

		#region log download / conversion

		/// <summary>
		/// Gets the server file information and loads it into IIS Analyzer objects
		/// </summary>
		private void GetServerFileInformation()
		{
			int count = 0;
			progressBar1.Value = 0;
			lbConvertingProgress.Items.Clear();
			lbConvertingProgress.Items.Add(ThreadingHelper.FormatLogRow("Start"));
			// fill log files list and get their number to indicate the progress
			for (int serverIndex = 0; serverIndex < session.ServerRecords.Count; serverIndex++)
			{
				ServerRecord currentServer = session.ServerRecords[serverIndex];

				if (currentServer.Enabled)
				{
					try
					{
						currentServer.LoadWebApplicationsFromActiveDirectory();

						// create a folder where log files will be downloaded
						string path = session.DownloadFolder + Path.DirectorySeparatorChar + currentServer.Name;

						if (!Directory.Exists(path))
							Directory.CreateDirectory(path);

						string[] subFolders = Directory.GetDirectories(currentServer.Path);
						foreach (string folderPath in subFolders)
						{
							// find the web application in the server applications list
							int applicationIndex = -1;
							for (int i = 0; i < currentServer.WebApplications.Count; i++)
							{
								if (currentServer.WebApplications[i].LogPath == Path.GetFileName(folderPath))
								{
									applicationIndex = i;
									break;
								}
							}

							// if server applications list doesn't contain current application, add it to the list 
							if (applicationIndex == -1)
							{
								string folderName = Path.GetFileName(folderPath);
								if (folderName.Length > 0)
								{
									if (folderName.Substring(0, 5) == "W3SVC")
									{
										WebApplication application = new WebApplication();
										application.Name = folderName;
										application.LogPath = folderName;

										currentServer.WebApplications.Add(application);

										applicationIndex = currentServer.WebApplications.Count - 1;
									}
								}
							}

							// if application is in the server applications list, get logs from its path
							if (applicationIndex != -1)
							{
								WebApplication currentApplication = currentServer.WebApplications[applicationIndex];

								currentApplication.LogFiles.Clear();

								lbConvertingProgress.Items.Add(ThreadingHelper.FormatLogRow("Searching for files in " + currentServer.Path + "\\" + folderPath));

								try
								{
									if (!Directory.Exists(path + "\\" + Path.GetFileName(folderPath)))
										Directory.CreateDirectory(path + "\\" + Path.GetFileName(folderPath));
								}
								catch
								{
									lbConvertingProgress.Items.Add(ThreadingHelper.FormatLogRow("Error: cannot create folder " + path + "\\" + Path.GetFileName(folderPath)));
								}

								string[] filePaths = null;

								try
								{
									// increment files counter for progress bar max value
									filePaths = Directory.GetFiles(folderPath, "*.log");
									count += filePaths.Length;
								}
								catch
								{
									lbConvertingProgress.Items.Add(ThreadingHelper.FormatLogRow("Error: cannot get list of files in folder " + folderPath));
								}

								// store found log file paths into application's logfiles list
								if (filePaths != null)
								{
									for (int i = 0; i < filePaths.Length; i++)
										currentApplication.LogFiles.Add(new FilePath(filePaths[i]));
								}

							}
						}
					}
					catch
					{
						lbConvertingProgress.Items.Add(ThreadingHelper.FormatLogRow("Error: cannot download log files for server " + currentServer.Name));
					}
				}
			}

			// if no files found, go back to the servers page
			if (count <= 0)
			{
				MessageBox.Show("No log files found. Please check whether selected server folder contains application folders with log files.");
				wizardControl.SelectedTab = pageChooseServers;
				//wizardControl.Back();
				return;
			}

			// max progressbar value contains number of files to download and process
			// (number found files * 2)
			progressBar1.Maximum = count * 2;
			progressBar1.Step = 1;

			btnNext.Enabled = false;
			btnBack.Enabled = false;

			// start downloading and processing thread
			thread = new Thread(new ThreadStart(DownloadAndConvertLogFiles));
			thread.Start();
		}

		/// <summary>
		/// Download and convert log files (thread procedure)
		/// </summary>
		private void DownloadAndConvertLogFiles()
		{
			Delegate delegateSetString = new ThreadingHelper.LabelDelegate(SetString);
			Delegate delegatePerformStep = new ThreadingHelper.ProgressBarDelegate(PerformProgressStep);
			Delegate delegateAddItemToListBox = new ThreadingHelper.ListBoxDelegate(AddItemToListBox);

			for (int serverIndex = 0; serverIndex < session.ServerRecords.Count; serverIndex++)
			{
				try
				{
					if (session.ServerRecords[serverIndex].Enabled)
					{

						ServerRecord currentServer = session.ServerRecords[serverIndex];

						string downloadPath;

						if (session.DownloadFolder == "")
							downloadPath = currentServer.Name;
						else
							downloadPath = session.DownloadFolder + Path.DirectorySeparatorChar + currentServer.Name;

						// list of the corrupt log files
						List<FilePath> ToDelete = new List<FilePath>();

						#region download log files from the server

						for (int webApplicationIndex = 0; webApplicationIndex < currentServer.WebApplications.Count; webApplicationIndex++)
						{
							WebApplication currentApplication = currentServer.WebApplications[webApplicationIndex];

							for (int logFileIndex = 0; logFileIndex < currentApplication.LogFiles.Count; logFileIndex++)
							{
								FilePath filePath = @currentApplication.LogFiles[logFileIndex];

								// update progress list box
								Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Downloading " + filePath.ToString() + " from " + currentServer.Path) });

								string newFile = downloadPath + Path.DirectorySeparatorChar + Path.GetFileName(Path.GetDirectoryName(filePath.FullPath)) + Path.DirectorySeparatorChar + filePath.ToString();

								// copy file from the server
								try
								{
									// if file with the same name exists, delete it
									if (File.Exists(newFile))
										File.Delete(newFile);
									File.Copy(filePath.FullPath, newFile);
								}
								catch
								{
									// update progress list box
									Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Error: cannot copy file " + filePath.FullPath + " to " + newFile) });
								}
								// if it's needed to delete log files from server, do so
								try
								{
									if (session.ClearServerLogFiles)
										File.Delete(filePath.FullPath);
								}
								catch
								{
									// update progress list box
									Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Warning: cannot delete file " + filePath.FullPath) });
								}
								// store downloaded file path into application's logfiles list
								currentApplication.LogFiles[logFileIndex].FullPath = newFile;

								// update progress bar
								Invoke(delegatePerformStep, new Object[] { progressBar1 });
							}
						}

						#endregion

						// convert downloaded log files into OpenXML Excel format
						for (int webApplicationIndex = 0; webApplicationIndex < currentServer.WebApplications.Count; webApplicationIndex++)
						{
							WebApplication currentApplication = currentServer.WebApplications[webApplicationIndex];

							for (int logFileIndex = 0; logFileIndex < currentApplication.LogFiles.Count; logFileIndex++)
							{
								try
								{
									FilePath logFilePath = @currentApplication.LogFiles[logFileIndex];

									// update progress list box
									Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Converting file " + logFilePath) });

									string newFilePath = logFilePath.FullPath;
									string fileName = Path.GetFileNameWithoutExtension(newFilePath);

									// indicates that file is broken and should be deleted from the list of processed files
									// (add it to the list of files to delete)
									bool AddToDelete = true;

									if (fileName.Length > 2)
									{
										// we choose a file converter based on the logfile name
										LogConverter loader = null;
										switch (fileName[0])
										{
											case 'e':
											case 'E':
												loader = new W3CExtendedLogConverter();
												break;
											case 'i':
											case 'I':
												loader = new IISLogConverter();
												break;
											case 'n':
											case 'N':
												loader = new NSCALogConverter();
												break;
										}

										if (loader != null)
										{
											string LogPath = Path.GetDirectoryName(newFilePath) + Path.DirectorySeparatorChar + "Event" + fileName.Substring(2, fileName.Length - 2) + ".xlsx";

											if (loader.Load(newFilePath, LogPath))
											{
												logFilePath.FullPath = LogPath;

												// store path to the converted log in the application's logfiles list
												currentApplication.LogFiles[logFileIndex] = logFilePath;//

												// correct application's start/end date
												if (currentApplication.StartDate > loader.StartDate || currentApplication.StartDate == DateTime.MaxValue)
													currentApplication.StartDate = loader.StartDate;

												if (currentApplication.EndDate < loader.EndDate || currentApplication.StartDate == DateTime.MaxValue)
													currentApplication.EndDate = loader.EndDate;
												AddToDelete = false;

											}
										}
									}


									if (AddToDelete)
									{
										ToDelete.Add(logFilePath);
										Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Error while converting file " + logFilePath) });
									}
									else
										Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Conversion finished: " + logFilePath) });

									try
									{
										if (session.ClearDownloadedLogFiles)
											File.Delete(newFilePath);
									}
									catch
									{
										Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Warning: cannot delete file " + newFilePath) });
									}

									// update progress bar
									Invoke(delegatePerformStep, new Object[] { progressBar1 });
								}
								catch (Exception ex)
								{
									if (!(ex is System.Threading.ThreadAbortException))
										Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("Error: " + ex.Message) });
								}
							}

							// remove corrupt log files
							foreach (FilePath filePath in ToDelete)
								currentApplication.LogFiles.Remove(filePath);
						}
					}

				}
				catch
				{
					Invoke(delegateAddItemToListBox, new Object[] { lbConvertingProgress, ThreadingHelper.FormatLogRow("There were errors during processing files of server " + session.ServerRecords[serverIndex]) });
				}
			}

			Delegate delegateFinalizeThread = new ThreadingHelper.VoidDelegate(FinalizeThread);
			BeginInvoke(delegateFinalizeThread);
		}

		#endregion

		/// <summary>
		/// Finishes thread work
		/// </summary>
		private void FinalizeThread()
		{
			try
			{
				if (thread != null)
				{
					if (thread.ThreadState != ThreadState.Suspended)
					{
						thread.Abort();
						thread.Join();
						thread = null;
					}
				}
			}
			finally
			{
				// wizardControl.Next();

				if (wizardControl.SelectedTab != pageCreatingReports)
				{
					lbConvertingProgress.Items.Add(ThreadingHelper.FormatLogRow("Report Finished"));
					btnNext.Enabled = true;
					btnBack.Enabled = true;
				}
				else
				{
					lbReportProgress.Items.Add(ThreadingHelper.FormatLogRow("Report Finished"));
					btnNext.Enabled = false;
					btnCancel.Text = "Close";
					session.Save();
				}


			}
		}

		/// <summary>
		/// Thread-safely sets label text
		/// </summary>
		/// <param name="s1">Label text</param>
		private void SetString(Label label, string labelString)
		{
			if (!label.InvokeRequired)
				label.Text = labelString;
			else
			{
				Delegate delegateSetString = new ThreadingHelper.LabelDelegate(SetString);
				Invoke(delegateSetString, new Object[] { label, labelString });
			}
		}

		/// <summary>
		/// Performs a threadsafe progress bar step
		/// </summary>
		private void PerformProgressStep(ProgressBar progressBar)
		{
			if (!progressBar.InvokeRequired)
				progressBar.PerformStep();
			else
			{
				Delegate delegatePerformStep = new ThreadingHelper.ProgressBarDelegate(PerformProgressStep);
				Invoke(delegatePerformStep);
			}
		}

		private void AddItemToListBox(ListBox listBox, object item)
		{
			if (!listBox.InvokeRequired)
			{
				listBox.Items.Add(item);
				listBox.SelectedIndex = listBox.Items.Count - 1;
			}
			else
			{
				Delegate delegateAddItemToListBox = new ThreadingHelper.ListBoxDelegate(AddItemToListBox);
				Invoke(delegateAddItemToListBox);
			}
		}

		//private void wizardControl_AfterSwitchPages( object sender, CristiPotlog.Controls.Wizard.AfterSwitchPagesEventArgs e )
		//{
		//    if ( e.NewIndex < e.OldIndex )
		//    {
		//        if ( e.NewIndex + e.OldIndex == 5 )
		//            wizardControl.SelectedTab = pageChooseServers;

		//        return;
		//    }

		//    switch ( e.NewIndex + e.OldIndex )
		//    {
		//        case 1:
		//            // Next pressed on the Servers page
		//            SaveServers();
		//            GetServerFileInformation();
		//            break;

		//        case 3:
		//            // Next pressed on the Downloading file page
		//            session.Save();
		//            LoadWebApplicationList();
		//            break;

		//        case 5:
		//            // Next pressed on the Applications page
		//            // initialize the progress page
		//            reportProgressBar.Value = 0;
		//            reportProgressBar.Maximum = GetReportInputsCount();
		//            reportProgressBar.Step = 1;

		//            btnNext.Enabled = false;
		//            btnBack.Enabled = false;

		//            foreach ( WebApplication webApplication in lbApplications.Items )
		//            {
		//                webApplication.StartDate = dtpReportPeriodFrom.Value;
		//                webApplication.EndDate = dtpReportPeriodTo.Value;
		//            }

		//            lbReportProgress.Items.Clear();
		//            lbReportProgress.Items.Add( ThreadingHelper.FormatLogRow( "Start" ) );

		//            thread = new Thread( new ThreadStart( CreateReports ) );
		//            thread.Start();
		//            break;

		//        //case 7:
		//        //    // Next pressed on the Creating reports page
		//        //    wizardControl.NextEnabled = false;
		//        //    session.Save();
		//        //    this.Close();
		//        //    break;
		//    }
		//}

		private void btnSaveOutputLog_Click(object sender, EventArgs e)
		{
			if (saveFileDialog.ShowDialog() == DialogResult.OK)
				FileHelper.SaveListBoxToFile(lbReportProgress, saveFileDialog.FileName);
		}

		private void btnSaveProcessingLog_Click(object sender, EventArgs e)
		{
			if (saveFileDialog.ShowDialog() == DialogResult.OK)
				FileHelper.SaveListBoxToFile(lbConvertingProgress, saveFileDialog.FileName);
		}
	}
}